#! /usr/bin/python
# -*- coding: utf-8 -*-

import re
import utils
import conf

class Validator:
    def __init__(self, rawString, validStyles=[]):
        self.rawString = rawString
        self.validStyles = validStyles
    def filter(self):
        return ''

#Identifier
class IdValidator(Validator):
    def filter(self):
        matchedObject = re.match('^[A-Za-z][A-Za-z0-9:\-_\.]*$', self.rawString)
        if matchedObject:
            return matchedObject.group(0)
        else:
            return ''

#Identifier which prefix can be a underscore '_'
class NameValidator(Validator):
    def filter(self):
        matchedObject = re.match('^[A-Za-z_][A-Za-z0-9:\-_\.]*$', self.rawString)
        if matchedObject:
            return matchedObject.group(0)
        else:
            return ''

class StyleValidator(Validator):
    def filter(self):
        safeStyles = ''
        stylesArray = self.rawString.split(';')
        for aStyle in stylesArray:
            if aStyle:
                styleNameValuePairsArray = aStyle.split(':')
                if len(styleNameValuePairsArray) == 2:
                    styleName = styleNameValuePairsArray[0]
                    styleValue = styleNameValuePairsArray[1]
                    if styleName in self.validStyles:
                        safeStyles += styleName + ':' + utils.htmlEncode(styleValue)
        return safeStyles

class NumberValidator(Validator):
    def filter(self):
        matchedObject = re.match('^[0-9]*$', self.rawString)
        if matchedObject:
            return matchedObject.group(0)
        else:
            return ''

class HtmlLengthValidator(Validator):
    def filter(self):
        matchedObject = re.match('^[0-9]+(px)?$', self.rawString)
        if matchedObject:
            return matchedObject.group(0)
        else:
            return ''

#Text which do not contains html tags (can contain any UTF-8 characters)
class PureTextValidator(Validator):
    def filter(self):
        return utils.htmlEncode(self.rawString)

class LinkValidator(Validator):
    def filter(self):
        matchedObject = re.match('^http(s)?:[A-Za-z0-9\-_\.\/\%\?=&]*$', self.rawString)
        if matchedObject:
            filteredLink = matchedObject.group(0)
            if filteredLink.startswith(conf.siteUrl + '/'):
                filteredLink = filteredLink[len(conf.siteUrl):]
            elif filteredLink.startswith(conf.appEngineUrl + '/'):
                filteredLink = filteredLink[len(conf.appEngineUrl):]
            #The htmlEncode is for xml.dom.minidom.parseString auto-decoding feature!! To make '&' to '&amp;'
            encodedLink = utils.htmlEncode(filteredLink)
            return encodedLink
        else:
            matchedObject = re.match('^\/[A-Za-z0-9\-_\.\/\%\?=&]*$', self.rawString)
            if matchedObject:
                #The htmlEncode is for xml.dom.minidom.parseString auto-decoding feature!! To make '&' to '&amp;'
                encodedLink = utils.htmlEncode(matchedObject.group(0))
                return encodedLink
            else:
                return ''

class MathXmlnsValidator(Validator):
    def filter(self):
        return 'http://www.w3.org/1998/Math/MathML'

class MfencedOpenValidator(Validator):
    def filter(self):
        matchedObject = re.match('^[{\[(]*$', self.rawString)
        if matchedObject:
            return matchedObject.group(0)
        else:
            return ''

class MfencedCloseValidator(Validator):
    def filter(self):
        matchedObject = re.match('^[}\])]*$', self.rawString)
        if matchedObject:
            return matchedObject.group(0)
        else:
            return ''

class MspaceWidthValidator(Validator):
    def filter(self):
        matchedObject = re.match('^[0-9]+(em)$', self.rawString)
        if matchedObject:
            return matchedObject.group(0)
        else:
            return ''

class MtdColumnalignValidator(Validator):
    def filter(self):
        if self.rawString == 'right' or self.rawString == 'left' or self.rawString == 'center':
            return self.rawString
        else:
            return ''
